﻿using System;
using System.Data;
using System.Data.SqlClient;
using FU.Capstones.IMS.Services.Common;
using FU.Capstones.IMS.Services.Common.DataContracts;
using FU.Capstones.IMS.Services.Common.Respondents;
using FU.Capstones.IMS.Services.DataContracts;
using FU.Capstones.IMS.Services.Interfaces;

namespace FU.Capstones.IMS.Services.DAOs
{
    public class AccountDAO : DAOBase, IAccountDAO
    {
        #region Implementation of IAccountDAO

        public SingleFeedback<Account> Login(Account account)
        {
            var feedback = new SingleFeedback<Account> {IsSuccessful = false, Data = account};
            try
            {
                var command = new SqlCommand("Login", imsConnection);

                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.AddWithValue("@Username", account.Username);
                command.Parameters.AddWithValue("@Password", account.Password);

                OpenConnection();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    if (reader.Read())
                    {
                        account.EmployeeID = Convert.ToInt32(reader["EmployeeID"]);
                        account.FullName = Convert.ToString(reader["FullName"]);

                        if (reader.NextResult())
                        {
                            while (reader.Read())
                            {
                                string temp = Convert.ToString(reader["Key"]);
                                if (!string.IsNullOrEmpty(temp))
                                {
                                    #region Employee rights

                                    if (
                                        !account.CanAddEmployee &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddEmployeeKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddEmployee = true;
                                        account.CanViewEmployee = true;
                                    }
                                    else if (
                                        !account.CanEditEmployee &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditEmployeeKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditEmployee = true;
                                        account.CanViewEmployee = true;
                                    }
                                    else if (
                                        !account.CanViewEmployee &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewEmployeeKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewEmployee = true;
                                    }
                                        #endregion

                                        #region EmploymentType rights

                                    else if (
                                        !account.CanAddEmploymentType &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddEmploymentTypeKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddEmploymentType = true;
                                        account.CanViewEmploymentType = true;
                                    }
                                    else if (
                                        !account.CanEditEmploymentType &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditEmploymentTypeKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditEmploymentType = true;
                                        account.CanViewEmploymentType = true;
                                    }
                                    else if (
                                        !account.CanViewEmploymentType &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewEmploymentTypeKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewEmploymentType = true;
                                    }

                                        #endregion
                                   
                                        #region Material rights

                                    else if (
                                        !account.CanAddMaterial &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddMaterialKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddMaterial = true;
                                        account.CanViewMaterial = true;
                                    }
                                    else if (
                                        !account.CanEditMaterial &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditMaterialKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditMaterial = true;
                                        account.CanViewMaterial = true;
                                    }
                                    else if (
                                        !account.CanViewMaterial &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewMaterialKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewMaterial = true;
                                    }

                                        #endregion
                                    
                                        #region OrderMaterial rights

                                    else if (
                                        !account.CanAddOrderMaterial &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddOrderMaterialKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddOrderMaterial = true;
                                        account.CanViewOrderMaterial = true;
                                    }
                                    else if (
                                        !account.CanEditOrderMaterial &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditOrderMaterialKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditOrderMaterial = true;
                                        account.CanViewOrderMaterial = true;
                                    }
                                    else if (
                                        !account.CanViewOrderMaterial &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewOrderMaterialKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewOrderMaterial = true;
                                    }

                                        #endregion
                                   
                                        #region OrderProduct rights

                                    else if (
                                        !account.CanAddOrderProduct &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddOrderProductKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddOrderProduct = true;
                                        account.CanViewOrderProduct = true;
                                    }
                                    else if (
                                        !account.CanEditOrderProduct &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditOrderProductKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditOrderProduct = true;
                                        account.CanViewOrderProduct = true;
                                    }
                                    else if (
                                        !account.CanViewOrderProduct &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewOrderProductKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewOrderProduct = true;
                                    }

                                        #endregion
                                    
                                        #region Partner rights

                                    else if (
                                        !account.CanAddPartner &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddPartnerKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddPartner = true;
                                        account.CanViewPartner = true;
                                    }
                                    else if (
                                        !account.CanEditPartner &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditPartnerKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditPartner = true;
                                        account.CanViewPartner = true;
                                    }
                                    else if (
                                        !account.CanViewPartner &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewPartnerKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewPartner = true;
                                    }

                                        #endregion
                                   
                                        #region Product rights

                                    else if (
                                        !account.CanAddProduct &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddProductKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddProduct = true;
                                        account.CanViewProduct = true;
                                    }
                                    else if (
                                        !account.CanEditProduct &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditProductKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditProduct = true;
                                        account.CanViewProduct = true;
                                    }
                                    else if (
                                        !account.CanViewProduct &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewProductKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewProduct = true;
                                    }

                                        #endregion
                                 
                                        #region Role rights

                                    else if (
                                        !account.CanAddRole &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddRoleKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddRole = true;
                                        account.CanViewRole = true;
                                    }
                                    else if (
                                        !account.CanEditRole &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditRoleKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditRole = true;
                                        account.CanViewRole = true;
                                    }
                                    else if (
                                        !account.CanViewRole &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewRoleKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewRole = true;
                                    }

                                        #endregion
                                    
                                        #region Warehouse rights

                                    else if (
                                        !account.CanAddWarehouse &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanAddWarehouseKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanAddWarehouse = true;
                                        account.CanViewWarehouse = true;
                                    }
                                    else if (
                                        !account.CanEditWarehouse &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanEditWarehouseKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanEditWarehouse = true;
                                        account.CanViewWarehouse = true;
                                    }
                                    else if (
                                        !account.CanViewWarehouse &&
                                        string.Compare(temp
                                                       ,
                                                       ConfigUtilities.GetStringKey(
                                                           InventoryConstants.AuthorizationKeys.CanViewWarehouseKey,
                                                           string.Empty)
                                                       , StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        account.CanViewWarehouse = true;
                                    }

                                    #endregion
                                }
                            }
                            feedback.Message = InventoryConstants.Messages.LoginSuccessfully;
                            feedback.IsSuccessful = true;
                            feedback.Data = account;
                        }
                        else
                        {
                            feedback.Message = InventoryConstants.Messages.Unauthorizated;
                            feedback.IsSuccessful = false;
                            account.EmployeeID = -1;
                        }
                    }
                    else
                    {
                        feedback.Message = InventoryConstants.Messages.Unauthorizated;
                        feedback.IsSuccessful = false;
                        account.EmployeeID = -1;
                    }
                }
                else
                {
                    feedback.Message = InventoryConstants.Messages.Unauthorizated;
                    feedback.IsSuccessful = false;
                    account.EmployeeID = -1;
                }


                //Log.Info("Login: {0}, {1}, {2}", account.Username, feedback.Message, DateTime.Now.ToString());
            }
            catch (SqlException e)
            {
                //Log.Error("Delete - SqlException: {0}, {1}, {2}", account.EmployeeID, e.StackTrace, DateTime.Now.ToString());
                feedback.Message = e.Message;
            }
            catch (Exception et)
            {
                //Log.Error("Delete - Exception: {0}, {1}, {2}", account.EmployeeID, et.StackTrace, DateTime.Now.ToString());
                feedback.Message = et.Message;
            }
            finally
            {
                CloseConnection();
            }
            return feedback;
        }

        public Feedback CheckIfUsernameExists(string usernameToCheck)
        {
            var feedback = new Feedback {IsSuccessful = false};

            try
            {
                var command = new SqlCommand("CheckIfUsernameExists", imsConnection);
                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.AddWithValue("@Username", usernameToCheck);

                OpenConnection();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    feedback.IsSuccessful = Convert.ToBoolean(reader["Exists"]);
                    if (feedback.IsSuccessful)
                    {
                        feedback.Message = InventoryConstants.Messages.UsernameExists;
                    }
                    else
                    {
                        feedback.Message = InventoryConstants.Messages.UsernameNotExists;
                    }
                }

                Log.Info("CheckIfUsernameExists: {0}, {1}, {2}", usernameToCheck, feedback.Message,
                         DateTime.Now.ToString());
            }
            catch (SqlException e)
            {
                Log.Error("CheckIfUsernameExists - SqlException: {0}, {1}, {2}", usernameToCheck, e.StackTrace,
                          DateTime.Now.ToString());
                feedback.Message = e.Message;
            }
            catch (Exception et)
            {
                Log.Error("CheckIfUsernameExists - Exception: {0}, {1}, {2}", usernameToCheck, et.StackTrace,
                          DateTime.Now.ToString());
                feedback.Message = et.Message;
            }
            finally
            {
                CloseConnection();
            }
            return feedback;
        }

        public Feedback ChangePassword(Account account)
        {
            if (account.GetType().Equals(typeof (Account)))
                return new Feedback(InventoryConstants.Messages.ChangePasswordFailed, false);

            var data = (NewPasswordData) account;

            var feedback = new Feedback {IsSuccessful = false};

            try
            {
                var command = new SqlCommand("ChangePassword", imsConnection);
                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.AddWithValue("@EmployeeID", data.EmployeeID);
                command.Parameters.AddWithValue("@Username", data.Username);
                command.Parameters.AddWithValue("@Password", data.Password);
                command.Parameters.AddWithValue("@NewPassword", data.NewPassword);

                OpenConnection();

                int rowAffect = command.ExecuteNonQuery();

                if (rowAffect < 1)
                {
                    feedback.Message = InventoryConstants.Messages.UpdateFailed;
                }
                else
                {
                    feedback.Message = InventoryConstants.Messages.UpdateSuccessfully;
                    feedback.IsSuccessful = true;
                }

                Log.Info("ChangePassword: {0}, {1}, {2}", account.EmployeeID, feedback.Message, DateTime.Now.ToString());
            }
            catch (SqlException e)
            {
                Log.Error("ChangePassword - SqlException: {0}, {1}, {2}", account.EmployeeID, e.StackTrace,
                          DateTime.Now.ToString());
                feedback.Message = e.Message;
            }
            catch (Exception et)
            {
                Log.Error("ChangePassword - Exception: {0}, {1}, {2}", account.EmployeeID, et.StackTrace,
                          DateTime.Now.ToString());
                feedback.Message = et.Message;
            }
            finally
            {
                CloseConnection();
            }
            return feedback;
        }

        public Feedback ResetPassword(Account account)
        {
            var feedback = new Feedback {IsSuccessful = false};

            try
            {
                var command = new SqlCommand("ResetPassword", imsConnection);
                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.AddWithValue("@EmployeeID", account.EmployeeID);
                command.Parameters.AddWithValue("@Username", account.Username);

                OpenConnection();

                int rowAffect = command.ExecuteNonQuery();

                if (rowAffect < 1)
                {
                    feedback.Message = InventoryConstants.Messages.DeleteFailed;
                }
                else
                {
                    feedback.Message = InventoryConstants.Messages.DeleteSuccessfully;
                    feedback.IsSuccessful = true;
                }

                Log.Info("ResetPassword: {0}, {1}, {2}", account.EmployeeID, feedback.Message, DateTime.Now.ToString());
            }
            catch (SqlException e)
            {
                Log.Error("ResetPassword - SqlException: {0}, {1}, {2}", account.EmployeeID, e.StackTrace,
                          DateTime.Now.ToString());
                feedback.Message = e.Message;
            }
            catch (Exception et)
            {
                Log.Error("ResetPassword - Exception: {0}, {1}, {2}", account.EmployeeID, et.StackTrace,
                          DateTime.Now.ToString());
                feedback.Message = et.Message;
            }
            finally
            {
                CloseConnection();
            }
            return feedback;
        }

        public bool Validate(string userName, string password)
        {
            try
            {
                var command = new SqlCommand("Validate", imsConnection);

                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.AddWithValue("@Username", userName);
                command.Parameters.AddWithValue("@Password", password);

                OpenConnection();

                SqlDataReader reader = command.ExecuteReader();

                return reader.HasRows;
                //Log.Info("Validate: {0}, {1}, {2}", account.Username, feedback.Message, DateTime.Now.ToString());
            }
            catch (SqlException e)
            {
                //Log.Error("Validate - SqlException: {0}, {1}, {2}", account.EmployeeID, e.StackTrace, DateTime.Now.ToString());
                return false;
            }
            catch (Exception et)
            {
                //Log.Error("Validate - Exception: {0}, {1}, {2}", account.EmployeeID, et.StackTrace, DateTime.Now.ToString());
                return false;
            }
            finally
            {
                CloseConnection();
            }
        }

        #endregion
    }
}